﻿using TheOutLetLibrary.Infraestrutura;
using System.Xml;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Collections;
using System;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Threading;
using System.Globalization;

namespace TheOutLetLibrary.Dominio {

    public class CarregadorNF {

        private IFactoryDAO factoryDAO;
        private NotaFiscal notaFiscal;
        private Remessa remessa;
        private IRemessaDAO remessaDAO;        
        private int qteNFsDoLote = 0;
        private int qteNFsLidas = 0;
        private int qteNFsImportadasComSucesso = 0;
        private bool novaRemessa = false;

        public CarregadorNF(IFactoryDAO factory, int idRemessa, int idEmpresa, int qteNFsDoLote) {
            factoryDAO = factory;
            this.qteNFsDoLote = qteNFsDoLote;
            using (OleDbConnection conexao = factoryDAO.GetConexao) {
                try {
                    conexao.Open();
                    OleDbTransaction transacao = conexao.BeginTransaction();
                    remessaDAO = factory.GetRemessaDAO(transacao);
                    if(idRemessa == 0) {
                        novaRemessa = true;
                        remessa = new Remessa {
                            XID_EMPRESA = idEmpresa,
                            XID_REMESSA = remessaDAO.BuscarProximaIdRemessa(),
                            DT_RECEBIMENTO_REMESSA = DateTime.Now
                        };
                    } else {
                        remessa = remessaDAO.Buscar(idRemessa);
                        remessa.DT_RECEBIMENTO_REMESSA = DateTime.Now;
                    }
                } catch (Exception) {
                    throw;
                }
            }
        }

        public string ImporteNF(string nomeArquivoXml) {

            string mensagem = "Carga efetuada com sucesso";
            qteNFsLidas++;

            try {                
                CarregueNF(nomeArquivoXml);
                SalveContextoNF();
                qteNFsImportadasComSucesso++;
            } catch (Exception ex) {
                mensagem = ex.Message;
            }

            if(qteNFsLidas == qteNFsDoLote) {
                GraveRemessa();
            }

            return mensagem;
        }

        private void GraveRemessa() {
            if(qteNFsImportadasComSucesso > 0) {
                using(OleDbConnection conexao = factoryDAO.GetConexao) {
                    try {
                        conexao.Open();
                        OleDbTransaction transacao = conexao.BeginTransaction();
                        IRemessaDAO remessaDAO = factoryDAO.GetRemessaDAO(transacao);
                        if(novaRemessa) {
                            remessaDAO.Incluir(remessa);
                        } else {
                            remessaDAO.Alterar(remessa);
                        }
                        transacao.Commit();
                    } catch(Exception) {
                        throw;
                    }
                }
            }
        }

        private void CarregueNF(string NomeArquivoXml) {

            XNamespace ad = "http://www.portalfiscal.inf.br/nfe";

            XElement notaFiscalXml = XElement.Load(NomeArquivoXml);

            XElement cabecalho = notaFiscalXml.Descendants(ad + "ide").First();

            notaFiscal = new NotaFiscal {
                XID_REMESSA = remessa.XID_REMESSA,
                XID_EMPRESA = remessa.XID_EMPRESA,
                NR_NF = cabecalho.Element(ad + "nNF").Value,
                DT_EMISSAO_NF = DateTime.Parse(cabecalho.Element(ad + "dEmi").Value),
            };

            IEnumerable<XElement> itensNF = from item in notaFiscalXml.Descendants(ad + "prod")
                                            select item;                                         

            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

            foreach(XElement item in itensNF) {
                notaFiscal.ItensNotaFiscal.Add(new ItemNotaFiscal {
                    //XID_PRODUTO = 1,
                    //xID_PRODUTO_NOTA_FISCAL = 1,
                    xID_REMESSA = notaFiscal.XID_REMESSA,
                    PRECO_NF_CONSIGNADO = decimal.Parse(item.Element(ad + "vUnCom").Value),
                    QT_ENVIADA = decimal.ToInt32(decimal.Parse(item.Element(ad + "qCom").Value)),
                    VL_TOTAL = decimal.Parse(item.Element(ad + "vProd").Value),
                    VL_UNITARIO = decimal.Parse(item.Element(ad + "vUnCom").Value),
                });
                notaFiscal.NR_TOTAL_DE_PECAS_INFORMADAS +=
                    decimal.ToInt32(decimal.Parse(item.Element(ad + "qCom").Value));
            }

            foreach(XElement item in itensNF) {
                notaFiscal.ProdutosNotaFiscal.Add(new Produto {
                    XID_EMPRESA = notaFiscal.XID_EMPRESA,
                    CD_MODELO_MARCA = item.Element(ad + "cProd").Value,
                    DSC_MODELO_MARCA = item.Element(ad + "xProd").Value,
                    DSC_MODELO_TOTLET = item.Element(ad + "xProd").Value,
                    NCM = item.Element(ad + "NCM").Value,
                    CFOP = item.Element(ad + "CFOP").Value,
                    PRECO_CONSIGNADO = decimal.Parse(item.Element(ad + "vUnCom").Value),
                    PRECO_POR = decimal.Parse(item.Element(ad + "vProd").Value)
                });
            }

            Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("pt-BR");

        }

        private void SalveContextoNF() {

            using(OleDbConnection conexao = factoryDAO.GetConexao) {

                OleDbTransaction transacao = null;

                try {

                    conexao.Open();
                    transacao = conexao.BeginTransaction();

                    IGenericDAO<NotaFiscal> nfDAO = factoryDAO.GetNotaFiscalDAO(transacao);
                    nfDAO.Inclua(notaFiscal);

                    IGenericDAO<ItemNotaFiscal> itemNFDAO = factoryDAO.GetItemNotaFiscalDAO(transacao);
                    IProdutoDAO produtoDAO = factoryDAO.GetProdutoDAO(transacao);

                    for(int i = 0; i < notaFiscal.ItensNotaFiscal.Count; i++) {
                        Produto produto = notaFiscal.ProdutosNotaFiscal[i];
                        ItemNotaFiscal itemNF = notaFiscal.ItensNotaFiscal[i];
                        itemNF.XID_PRODUTO = produtoDAO.AcheOuInclua(produto);
                        itemNF.XID_NOTA_FISCAL = notaFiscal.XID_NOTA_FISCAL;
                        itemNFDAO.Inclua(itemNF);
                    }

                    transacao.Commit();

                } catch {
                    transacao.Rollback();
                    throw;
                }

            }

        }

    }

}
